#endif
#if defined WINDOWSNT || defined HAVE_NTGUI
+ /* Grab our malloc arena space now, before anything important
+ happens. This relies on the static heap being needed only in
+ temacs and only if we are going to dump with unexec. */
+ bool use_dynamic_heap = false;
+ if (strstr (argv[0], "temacs") != NULL)
+ {
+ eassert (temacs);
+ /* Note that gflags are set at this point only if we have been
+ called with the --temacs=METHOD option. We assume here that
+ temacs is always called that way, otherwise the functions
+ that rely on gflags, like will_dump_with_pdumper_p below,
+ will not do their job. */
+ use_dynamic_heap = will_dump_with_pdumper_p ();
+ }
+ else
+ use_dynamic_heap = true;
+ init_heap (use_dynamic_heap);
/* Set global variables used to detect Windows version. Do this as
- early as possible. (unexw32.c calls this function as well, but
+ early as possible. (w32proc.c calls this function as well, but
the additional call here is harmless.) */
cache_system_info ();
#ifdef WINDOWSNT
#include "w32heap.h"
-/* Basically, our "initialized" flag. */
-BOOL using_dynamic_heap = FALSE;
-
void get_section_info (file_data *p_file);
void copy_executable_and_dump_data (file_data *, file_data *);
void dump_bss_and_heap (file_data *p_infile, file_data *p_outfile);
exit (1);
}
- /* Set the flag (before dumping). */
- using_dynamic_heap = TRUE;
-
copy_executable_and_dump_data (&in_file, &out_file);
- /* Unset it because it is plain wrong to keep it after dumping.
- Malloc can still occur! */
- using_dynamic_heap = FALSE;
-
/* Patch up header fields; profiler is picky about this. */
{
PIMAGE_DOS_HEADER dos_header;
Memory allocation scheme for w32/w64:
- Buffers are mmap'ed using a very simple emulation of mmap/munmap
- - During the temacs phase:
+ - During the temacs phase, if unexec is to be used:
* we use a private heap declared to be stored into the `dumped_data'
* unfortunately, this heap cannot be made growable, so the size of
blocks it can allocate is limited to (0x80000 - pagesize)
We use a very simple first-fit scheme to reuse those blocks.
* we check that the private heap does not cross the area used
by the bigger chunks.
- - During the emacs phase:
+ - During the emacs phase, or always if pdumper is used:
* we create a private heap for new memory blocks
* we make sure that we never free a block that has been dumped.
Freeing a dumped block could work in principle, but may prove
than half of the size stated below. It would be nice to find a way
to build only the first bootstrap-emacs.exe with the large size,
and reset that to a lower value afterwards. */
-#if defined _WIN64 || defined WIDE_EMACS_INT
-# define DUMPED_HEAP_SIZE (23*1024*1024)
+#ifdef CANNOT_DUMP
+/* We don't use dumped_data[] when CANNOT_DUMP, so define to a small
+ size that won't matter. */
+# define DUMPED_HEAP_SIZE 10
#else
-# define DUMPED_HEAP_SIZE (13*1024*1024)
+# if defined _WIN64 || defined WIDE_EMACS_INT
+# define DUMPED_HEAP_SIZE (23*1024*1024)
+# else
+# define DUMPED_HEAP_SIZE (13*1024*1024)
+# endif
#endif
static unsigned char dumped_data[DUMPED_HEAP_SIZE];
static unsigned char *bc_limit;
/* Handle for the private heap:
- - inside the dumped_data[] array before dump,
- - outside of it after dump.
+ - inside the dumped_data[] array before dump with unexec,
+ - outside of it after dump, or always if pdumper is used.
*/
HANDLE heap = NULL;
http://stackoverflow.com/questions/307060/what-is-the-purpose-of-allocating-pages-in-the-pagefile-with-createfilemapping */
/* This is the function to commit memory when the heap allocator
- claims for new memory. Before dumping, we allocate space
- from the fixed size dumped_data[] array.
+ claims for new memory. Before dumping with unexec, we allocate
+ space from the fixed size dumped_data[] array.
*/
static NTSTATUS NTAPI
dumped_data_commit (PVOID Base, PVOID *CommitAddress, PSIZE_T CommitSize)
typedef WINBASEAPI BOOL (WINAPI * HeapSetInformation_Proc)(HANDLE,HEAP_INFORMATION_CLASS,PVOID,SIZE_T);
#endif
-#ifdef HAVE_PDUMPER
-BOOL using_dynamic_heap = FALSE;
-#endif
-
void
-init_heap (void)
+init_heap (bool use_dynamic_heap)
{
-#ifdef HAVE_PDUMPER
- using_dynamic_heap = TRUE;
-#endif
- if (using_dynamic_heap)
+ /* FIXME: Remove the condition, the 'else' branch below, and all the
+ related definitions and code, including dumped_data[], when unexec
+ support is removed from Emacs. */
+ if (use_dynamic_heap)
{
-#ifndef MINGW_W64
- unsigned long enable_lfh = 2;
-#endif
-
/* After dumping, use a new private heap. We explicitly enable
the low fragmentation heap (LFH) here, for the sake of pre
Vista versions. Note: this will harmlessly fail on Vista and
heap = HeapCreate (0, 0, 0);
#ifndef MINGW_W64
+ unsigned long enable_lfh = 2;
/* Set the low-fragmentation heap for OS before Vista. */
HMODULE hm_kernel32dll = LoadLibrary ("kernel32.dll");
HeapSetInformation_Proc s_pfn_Heap_Set_Information =
the_free_fn = free_after_dump;
}
}
- else
+ else /* Before dumping with unexec: use static heap. */
{
/* Find the RtlCreateHeap function. Headers for this function
are provided with the w32 DDK, but the function is available
return p;
}
+/* FIXME: The *_before_dump functions should be removed when pdumper
+ becomes the only dumping method. */
void *
malloc_before_dump (size_t size)
{
}
}
-#ifdef ENABLE_CHECKING
+#if !defined (CANNOT_DUMP) && defined (ENABLE_CHECKING)
void
report_temacs_memory_usage (void)
{
static CRITICAL_SECTION crit_sig;
+/* Catch memory allocation before the heap allocation scheme is set
+ up. These functions should never be called, unless code is added
+ early on in 'main' that runs before init_heap is called. */
+_Noreturn void * malloc_before_init (size_t);
+_Noreturn void * realloc_before_init (void *, size_t);
+_Noreturn void free_before_init (void *);
+
+_Noreturn void *
+malloc_before_init (size_t size)
+{
+ fprintf (stderr,
+ "error: 'malloc' called before setting up heap allocation; exiting.\n");
+ exit (-1);
+}
+
+_Noreturn void *
+realloc_before_init (void *ptr, size_t size)
+{
+ fprintf (stderr,
+ "error: 'realloc' called before setting up heap allocation; exiting.\n");
+ exit (-1);
+}
+
+_Noreturn void
+free_before_init (void *ptr)
+{
+ fprintf (stderr,
+ "error: 'free' called before setting up heap allocation; exiting.\n");
+ exit (-1);
+}
extern BOOL ctrl_c_handler (unsigned long type);
DebugBreak ();
#endif
+ the_malloc_fn = malloc_before_init;
+ the_realloc_fn = realloc_before_init;
+ the_free_fn = free_before_init;
+
/* Cache system info, e.g., the NT page size. */
cache_system_info ();
- /* Grab our malloc arena space now, before CRT starts up. */
- init_heap ();
-
/* This prevents ctrl-c's in shells running while we're suspended from
having us exit. */
SetConsoleCtrlHandler ((PHANDLER_ROUTINE) ctrl_c_handler, TRUE);